/*
 * Copyright 2008 aileron.cc, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cc.aileron.commons.accessor.factory;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import cc.aileron.commons.accessor.PojoAccessor;
import cc.aileron.commons.accessor.PojoAccessorFactory;
import cc.aileron.commons.utility.PrimitiveArrayWrapperUtils;

/**
 * PojoAccessorIterator
 * 
 * @author Aileron
 * 
 */
public class PojoAccessorIterator implements
    Iterator<PojoAccessor<?>>,
    Iterable<PojoAccessor<?>>
{
    /**
     * null-object
     */
    private static final Iterator<Object> nullIterator = new Iterator<Object>()
    {
        /*
         * (非 Javadoc)
         * 
         * @see java.util.Iterator#hasNext()
         */
        public boolean hasNext()
        {
            return false;
        }

        /*
         * (非 Javadoc)
         * 
         * @see java.util.Iterator#next()
         */
        public Object next()
        {
            throw new NoSuchElementException();
        }

        /*
         * (非 Javadoc)
         * 
         * @see java.util.Iterator#remove()
         */
        public void remove()
        {
            throw new UnsupportedOperationException();
        }
    };

    public boolean hasNext()
    {
        return targetObject.hasNext();
    }

    public Iterator<PojoAccessor<?>> iterator()
    {
        return this;
    }

    public PojoAccessor<?> next()
    {
        return factory.accessor(targetObject.next());
    }

    public void remove()
    {
        throw new UnsupportedOperationException();
    }

    /**
     * 型判別を行い、Iteratorを返す
     * 
     * @param object
     * @return
     */
    @SuppressWarnings("unchecked")
    private Iterator<Object> typeCompareToIterator(final Object object)
    {
        if (object == null)
        {
            return nullIterator;
        }
        if (object instanceof Iterable)
        {
            return ((Iterable) object).iterator();
        }
        if (object instanceof Iterator)
        {
            return (Iterator<Object>) object;
        }
        if (object instanceof List)
        {
            return ((List) object).iterator();
        }
        if (object.getClass().isArray())
        {
            final List<Object> primitiveList = PrimitiveArrayWrapperUtils
                    .convert(object);
            if (primitiveList != null)
            {
                return primitiveList.iterator();
            }
            final Object[] array = (Object[]) object;
            final List<Object> list = Arrays.asList(array);
            return list != null ? list.iterator() : Arrays.asList().iterator();
        }
        return Arrays.asList().iterator();
    }

    /**
     * constructor
     * 
     * @param factory
     * @param object
     */
    public PojoAccessorIterator(
        final PojoAccessorFactory factory,
        final Object object)
    {
        this.factory = factory;
        this.targetObject = typeCompareToIterator(object);
    }

    /**
     * 対象
     */
    private final Iterator<Object> targetObject;

    /**
     * factory
     */
    private final PojoAccessorFactory factory;
}
